package com.common.service;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;

import com.abstrack.mapper.ComMapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.common.api.Constant;
import com.common.api.exception.CommonException;
import com.common.api.model.PageModel;
import com.common.error.CommonError;
import com.common.iface.MapperDtoIface;
import com.common.web.dto.request.FuzzyPageDTO;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;

/**
 * <p>
 * 应用服务类
 * </p>
 *
 * @author ficus
 * @param <M>
 * @since 2020-06-29
 */
public abstract class MapperService<PO,DTO extends PO, Mapper extends ComMapper<PO>> extends BaseService<PO, DTO,Mapper> implements MapperDtoIface<DTO,Mapper>{
	
	@Value("${mybatis-plus.configuration.map-underscore-to-camel-case:false}")
	private boolean mapUnderscoreToCamelCase;
	
	@Override
	public PageModel<DTO> queryList(FuzzyPageDTO fuzzyPageDTO) {
		Integer startPage =fuzzyPageDTO.getStartPage();
		Integer pageSize= fuzzyPageDTO.getPageSize();
		QueryWrapper<PO> query = Wrappers.query();
		// 排序
		if(StringUtils.isNoneEmpty(getOrderBy())) {
			query.orderByAsc(convertKey(getOrderBy()));
		}
		//模糊查询
		String searchKey=fuzzyPageDTO.getSearchKey();
		List<String> keyList=getSearchKeyList();
		if(CollectionUtil.isNotEmpty(keyList)&&StringUtils.isNotBlank(searchKey)) {
			String key=keyList.get(0);
			if(StringUtils.isNoneEmpty(key)) {
				query.and(t -> {
                    t.like(convertKey(key), searchKey);
                    for (int i = 1; i < keyList.size(); i++) {
                        t.or().like(convertKey(keyList.get(i)), searchKey);
                    }
                });
			}
		}
		// 时间过滤
		String dateKey=getDateKey();
		if(StringUtils.isNoneEmpty(dateKey)) {
			// 根据时间间隔过滤
			Date startDate=fuzzyPageDTO.getStartDateTime();
			Date endDate=fuzzyPageDTO.getEndDateTime();
			if(startDate!=null) {
				query.ge(convertKey(dateKey), startDate);
			}
			if(endDate!=null) {
				query.lt(convertKey(dateKey), endDate);
			}
		}
		// 相等条件查询
		Map<String,Object> equalMap=fuzzyPageDTO.getEqualHash();
		if(MapUtil.isNotEmpty(equalMap)) {
			equalMap.forEach((key, value) -> {
				String keyText = convertKey(key);
                if (StringUtils.isNoneEmpty(keyText)) {
                    if (value == null) {
                        query.isNull(keyText);
                    } else {
                        if (StringUtils.isNotEmpty(value.toString())) {
                            query.eq(keyText, value);
                        }
                    }
                }
            });
		}
		
		// in 条件查询
		Map<String,List<Object>> inMap=fuzzyPageDTO.getInHash();
		if(MapUtil.isNotEmpty(inMap)) {
			inMap.forEach((key, value) -> {
				String keyText = convertKey(key);
                if (StringUtils.isNoneEmpty(keyText)) {
                    if (CollectionUtil.isNotEmpty(value)) {
                        query.in(keyText, value);
                    }
                }
            });
		}
		// 分页查询
		Page<PO> page=  PageHelper.startPage(startPage, pageSize).doSelectPage(
			() -> getBaseMapper().selectList(query)
		);
		return convertToPageBean(page);
	}
	
	@Override
	public DTO get(Serializable id) {
		PO po= getBaseMapper().selectById(id);
		return convertToDto(po);
	}
	
	@Override
	public int saveDto(DTO dto) {
		Object id=null;
		try {
			Method method=dto.getClass().getMethod(Constant.GET+StringUtils.capitalize(getIdKey()));
			id=method.invoke(dto);
		} catch (Exception e) {
			e.printStackTrace();
		}
		int result=0;
		if(id==null) {
			throw new CommonException(CommonError.codeVlueNotExist);
		}else {
			PO exist=getBaseMapper().selectById((Serializable)id);
			if(exist==null) {
				result=getBaseMapper().insert(dto);
			}else {
				result=getBaseMapper().updateById(dto);		
			}
		}
		return result;
	}

	@Override
	public int add(DTO dto) {
		return getBaseMapper().insert(dto);
	}
	
	@Override
	public int modify(DTO dto) {
		return getBaseMapper().updateById(dto);
	}
	
	@Override
	public int dels(List<String> idList) {
		if(CollectionUtil.isEmpty(idList)) {
			return 0;
		}
		return getBaseMapper().deleteBatchIds(idList);
	}
	
	/**
	 * 获取ID字段名称
	 * @return
	 */
	protected String getIdKey() {
		return "id";
	};
	
	/**
	 * 获取ID数据库名称
	 * @return
	 */
	protected String getIdColumn() {
		return "id";
	}
	
	/**
	 * 数据库的排序字段
	 * @return
	 */
	protected String getOrderBy() {
		String orderBy=getIdColumn();
    	return orderBy;
    }
	
	/**
     * 数据库的模糊查询字段
     * @return
     */
	protected abstract List<String> getSearchKeyList();

    /**
     * 数据库日期匹配字段
     * @return
     */
    public String getDateKey() {
		return "";
	}
    
    /**
     * 是否将驼峰字段转成数据库下划线字段
     * @param key
     * @return
     */
    private String convertKey(String key) {
		 if (StringUtils.isNoneEmpty(key)) {
	     	if(mapUnderscoreToCamelCase) {
	     		String keyText = StrUtil.toUnderlineCase(key);
	     		return keyText;
	     	}
		 }
		 return key;
    }
}
